/**
 * Please modify this class to meet your needs This class is not complete
 */

package com.projetIE.prudhomme_duisit;

import java.io.StringWriter;
import java.util.Collection;
import java.util.Iterator;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.xml.bind.JAXBContext;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.projetIE.prudhomme_duisit.listener.ReceiveListener;

/**
 * This class was generated by Apache CXF 2.1.4 Thu Sep 29 15:35:46 CEST 2011
 * Generated source version: 2.1.4
 * 
 */

@javax.jws.WebService(serviceName = "prudhomme_duisit", portName = "prudhomme_duisit_SOAP", targetNamespace = "http://www.projetIE.com/prudhomme_duisit/", wsdlLocation = "document.wsdl", endpointInterface = "com.projetIE.prudhomme_duisit.PrudhommeDuisit")
public class PrudhommeDuisitImpl implements PrudhommeDuisit {
	
	private ConnectionFactory	                   connectionFactory;
	
	private Connection	                           connection;
	
	private Destination	                           destination;
	
	private Destination	                           receive;
	
	private Multimap<String, GetSituationResponse>	storage	= HashMultimap.create();
	
	/**
	 * 
	 */
	public static Logger	                       LOG	    = Logger.getLogger(PrudhommeDuisitImpl.class);
	
	/**
	 * 
	 */
	public PrudhommeDuisitImpl() {
		connect();
		initReceiveListener();
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.projetIE.prudhomme_duisit.PrudhommeDuisit#getSituation(com.projetIE
	 * .prudhomme_duisit.GetSituationRequest parameters )*
	 */
	public GetSituationResponse getSituation(GetSituationRequest parameters) {
		LOG.info("Executing operation getSituation");
		System.out.println(parameters);
		
		try {
			return retrieveMessage(parameters.getClient());
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new RuntimeException(ex);
		}
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.projetIE.prudhomme_duisit.PrudhommeDuisit#postRequest(com.projetIE
	 * .prudhomme_duisit.PostRequestRequest parameters )*
	 */
	public PostRequestResponse postRequest(PostRequestRequest parameters) {
		LOG.info("Executing operation postRequest with / " + parameters.getClient() + " / "
		        + parameters.getPays() + " / " + parameters.getVille());
		PostRequestResponse response = new PostRequestResponse();
		boolean success;
		try {
			success = sendMessages(parameters);
			response.setSuccess(success);
			return response;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new RuntimeException(ex);
		}
	}
	
	protected static String domToString(final Document _document) throws TransformerException {
		TransformerFactory tFactory = TransformerFactory.newInstance();
		Transformer transformer = tFactory.newTransformer();
		transformer.setOutputProperty(OutputKeys.INDENT, "yes");
		transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
		DOMSource source = new DOMSource(_document);
		StringWriter sw = new StringWriter();
		StreamResult result = new StreamResult(sw);
		transformer.transform(source, result);
		return sw.toString();
	}
	
	/**
	 * @param client
	 * @param d
	 */
	public void addMessageToStorage(String client, GetSituationResponse d) {
		LOG.info(client + d);
		storage.put(client, d);
	}
	
	private void connect() {
		Context jndiContext;
		try {
			jndiContext = new InitialContext();
			connectionFactory = (ConnectionFactory) jndiContext.lookup("connectionFactory");
			destination = (Destination) jndiContext.lookup("requestQueue");
			receive = (Destination) jndiContext.lookup("responseQueue");
			connection = connectionFactory.createConnection();
		} catch (NamingException e) {
			LOG.error("Naming exception : connection failed");
			e.printStackTrace();
			if (connection != null) {
				try {
					connection.close();
				} catch (JMSException a) {
				}
			}
			System.exit(1);
		} catch (JMSException e) {
			LOG.error("JMS error : connection failed");
			e.printStackTrace();
			if (connection != null) {
				try {
					connection.close();
				} catch (JMSException a) {
				}
			}
		}
		
	}
	
	private boolean sendMessages(PostRequestRequest p) {
		
		boolean success = true;
		try {
			Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
			MessageProducer producer = session.createProducer(destination);
			
			if (p.getClient() == null) {
				LOG.info("client not exist ignoring request");
				success = false;
			} else {
				
				TextMessage message = session.createTextMessage(domToString(p.generatedDom()));
				producer.send(message);
			}
		} catch (JMSException e) {
			LOG.error("JMS error : message not send");
			e.printStackTrace();
			success = false;
		} catch (TransformerException e) {
			LOG.error("Transformer error : message not send");
			e.printStackTrace();
			success = false;
		}
		return success;
	}
	
	private void initReceiveListener() {
		try {
			Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
			MessageConsumer consumer = session.createConsumer(receive);
			ReceiveListener listener = new ReceiveListener(this);
			
			consumer.setMessageListener(listener);
			connection.start();
		} catch (JMSException e) {
			LOG.error("JMS error : Listener not initate");
			e.printStackTrace();
			if (connection != null) {
				try {
					connection.close();
				} catch (JMSException a) {
				}
			}
		}
	}
	
	private GetSituationResponse retrieveMessage(String client) {
		JAXBContext context;
		GetSituationResponse _return = null;
		Collection<GetSituationResponse> result = null;
		try {
			result = storage.get(client);
		} catch (Exception e) {
			LOG.error("Retireve message error : get failed");
		}
		try {
			Iterator<GetSituationResponse> iter = result.iterator();
			_return = iter.next();
		} catch (Exception e) {
			LOG.error("Retireve message error : iterator failed");
		}
		try {
			storage.remove(client, _return);
		} catch (Exception e) {
			LOG.error("Retireve message error : remove failed");
		}
		
		return _return;
	}
	
}
